# React - 03

今天算是解除了一点真东西,生命周期这里感觉和vue比还是难理解。

# 父子组件通信

React是单向数据流,从上至下,也就是说爹可以教育儿子,儿子不能教育爹。但是儿子可以使用爹的技巧来感化爹。

# 父 -> 子

和Vue类似都是用到了props来进行传递

<!--father-->

<Item attrbuteName={value}/>
// son

const value = this.props.attrbuteName

# 子 -> 父

问题来了,怎么感化,爹教会儿子方法,儿子通过爹的方法让爹自己改变

<!--father-->

<Item attrbuteName={value} funcitonName={() => this.funcitonName} />

functionName () {}
<!--son-->

<li onClick={() => this.props.functionName}></li>

# React developer tools

好玩意,跟Vue的差不多,比Vue的好用。说是不需要用console,过几天再来评价。

# propTypes 类型检查

有点类似Vue,又有点类似ts的interface,谁抄谁,又有谁知道呢。

# React

import PropTypes from 'prop-types'
import React from 'React'


class MyComponent extends Component {}

MyComponent.propTypes = {
    optionalArray: PropTypes.array.isRequired,
    optionalBool: PropTypes.bool,
    optionalFunc: PropTypes.func,
    optionalNumber: PropTypes.number,
    optionalObject: PropTypes.object,
    optionalString: PropTypes.string,
    optionalSymbol: PropTypes.symbol,
    optionalNode: PropTypes.node,
    optionalMessage:PropTypes.instanceOf(Message)
}
// 默认值
MyComponent.defaultProps = {
    optionalArray: [123,456],
}

要是必须又那就加==isRequired== 要是啥都行,那就any

# Vue

export default {
    props: {
        a: [String, Number],
        b:{
            type: String,
            default: 100,
            required: true
        }
    }
}

还是Vue写着简单。

# ref

唉,和Vue又差不多。

# React


<ul ref={ul => this.ul = ul}>
    <li>1</li>
    <li>2</li>
</ul>


ul => this.ul = ul 固定写法,优点一大堆。

this.setData({
    a: '123'
}, () => {
    this.ul.querySelectAll('li').length
})

  1. this.ul 返回的是dom节点
  1. setData 是一个异步方法

# Vue

<template>
  <div id="app">
    <div ref="testDom">11111</div>
    <button @click="getTest">获取test节点</button>
  </div>
</template>

<script>
export default {
  methods: {
    getTest() {
      console.log(this.$refs.testDom)
    }
  }
};
</script>

# 生命周期

这块东西好啊,看的16.x的教程,人家已经更新到17.x

生命周期分为三个部分:

  1. init 初始化
  2. mount dom挂载
  3. update
    • state
    • props
  4. unmount

以下按照执行顺序排列,render除外


// 废弃如果要使用UNSAFE_
componentWillMount() {}
// 渲染中
render() {}
// dom挂载完成
componentDidMount() {}
// 废弃
componentWillReceiveProps(nextProps) {}
// 是否决定重新渲染组件
shouldComponentUpdate(nextProps, nextState) {}
// 废弃
componentWillUpdate(nextProps, nextState) {}
// 组件完成重新渲染
componentDidUpdate(prevProps, prevState) {}
// 组件移除前
componentWillUnmount() {}


17.x 新增周期

// 代替componentWillReceiveProps
static componentWillReceiveProps(props, state) {
    return null
}
getSnapshotBeforeUpdate(prevProps, prevState) {
    return null
}

==getDerivedStateFromProps==:从props中获取state,仅存在于子组件中

注意:组件第一次存在于dom中函数是不会被执行的

==getSnapshotBeforeUpdate==: 在组件更新前获取快照,有个例子 (opens new window),必须配合ComponentDidUpdate使用。

学是学完了,缺少应用场景,待实战。

2021-05-27

import React, { Component } from 'react'
import './new.css'
class News extends Component {
  constructor (props) {
    super(props)
    this.state = {
      list: [
        'news-0'
      ]
    }
  }
  render () {
    return (
      <ul ref={ul => {this.ul = ul}} className='ul'>
        {this.state.list.map((item, index) => {
          return <li key={index}>{item}</li>
        })}
      </ul>

    )
  }
  componentDidMount () {
    this.timer = setInterval(() => {
      let data = [`news-${this.state.list.length}`, ...this.state.list]
      this.setState({
        list: data
      })
    }, 2000)
  }
  getSnapshotBeforeUpdate (prevProps, prevState) {
     return this.ul.scrollHeight
  }

  componentDidUpdate (prevProps, prevState,height) {
    console.log(this.ul.scrollHeight)
    console.log(height)
    this.ul.scrollTop += this.ul.scrollHeight - height
  }

  componentWillUnmount () {
    clearInterval(this.timer)
  }
}


export default News


以上。